package v1

import (
	"fmt"
	"os"
	"os/exec"
	"path/filepath"
	"sort"
	"time"
	"wms/pkg/common"
	"wms/pkg/logger"

	"github.com/gin-gonic/gin"
	"go.uber.org/zap"
)

// BackupController 备份控制器
type BackupController struct {
	backupDir string
}

// BackupInfo 备份信息
type BackupInfo struct {
	Filename   string    `json:"filename"`    // 文件名
	Size       int64     `json:"size"`        // 文件大小
	CreateTime time.Time `json:"create_time"` // 创建时间
}

// NewBackupController 创建备份控制器
func NewBackupController() *BackupController {
	backupDir := "./backups"
	if _, err := os.Stat(backupDir); os.IsNotExist(err) {
		err := os.MkdirAll(backupDir, 0755)
		if err != nil {
			logger.Error("创建备份目录失败", zap.Error(err))
		}
	}
	return &BackupController{
		backupDir: backupDir,
	}
}

// Backup godoc
// @Summary 创建数据库备份
// @Description 创建一个新的数据库备份文件
// @Tags 数据库备份
// @Accept json
// @Produce json
// @Security Bearer
// @Success 200 {object} common.Response{data=map[string]string{file=string}} "成功"
// @Failure 400 {object} common.Response "请求错误"
// @Failure 500 {object} common.Response "内部错误"
// @Router /backup [post]
func (c *BackupController) Backup(ctx *gin.Context) {
	filename := fmt.Sprintf("backup_%s.sql", time.Now().Format("20060102_150405"))
	backupPath := filepath.Join(c.backupDir, filename)

	// TODO: 使用实际的数据库配置
	cmd := fmt.Sprintf("mysqldump -u root -p your_password your_database > %s", backupPath)
	if err := exec.Command("sh", "-c", cmd).Run(); err != nil {
		logger.Error("执行备份命令失败", zap.Error(err), zap.String("path", backupPath))
		common.Error(ctx, fmt.Errorf("备份失败: %v", err))
		return
	}

	logger.Info("数据库备份成功", zap.String("filename", filename))
	common.Success(ctx, gin.H{"file": filename})
}

// Restore godoc
// @Summary 恢复数据库备份
// @Description 从指定的备份文件恢复数据库
// @Tags 数据库备份
// @Accept multipart/form-data
// @Produce json
// @Security Bearer
// @Param filename formData string true "备份文件名"
// @Success 200 {object} common.Response "成功"
// @Failure 400 {object} common.Response "请求错误"
// @Failure 500 {object} common.Response "内部错误"
// @Router /backup/restore [post]
func (c *BackupController) Restore(ctx *gin.Context) {
	filename := ctx.PostForm("filename")
	if filename == "" {
		logger.Warn("未指定备份文件")
		common.Error(ctx, fmt.Errorf("未指定备份文件"))
		return
	}

	backupPath := filepath.Join(c.backupDir, filename)
	if _, err := os.Stat(backupPath); os.IsNotExist(err) {
		logger.Warn("备份文件不存在", zap.String("path", backupPath))
		common.Error(ctx, fmt.Errorf("备份文件不存在"))
		return
	}

	// TODO: 使用实际的数据库配置
	cmd := fmt.Sprintf("mysql -u root -p your_password your_database < %s", backupPath)
	if err := exec.Command("sh", "-c", cmd).Run(); err != nil {
		logger.Error("执行恢复命令失败", zap.Error(err), zap.String("path", backupPath))
		common.Error(ctx, fmt.Errorf("恢复失败: %v", err))
		return
	}

	logger.Info("数据库恢复成功", zap.String("filename", filename))
	common.Success(ctx, nil)
}

// GetList godoc
// @Summary 获取备份列表
// @Description 获取系统备份文件列表
// @Tags 系统备份
// @Accept json
// @Produce json
// @Security Bearer
// @Success 200 {object} common.Response{data=[]BackupInfo} "成功"
// @Failure 400 {object} common.Response "请求错误"
// @Failure 500 {object} common.Response "内部错误"
// @Router /system/backups [get]
func (c *BackupController) GetList(ctx *gin.Context) {
	files, err := os.ReadDir(c.backupDir)
	if err != nil {
		logger.Error("读取备份目录失败", zap.Error(err))
		common.Error(ctx, err)
		return
	}

	backups := make([]BackupInfo, 0)
	for _, file := range files {
		if file.IsDir() {
			continue
		}

		info, err := file.Info()
		if err != nil {
			logger.Error("获取文件信息失败", zap.Error(err), zap.String("file", file.Name()))
			continue
		}

		backups = append(backups, BackupInfo{
			Filename:   file.Name(),
			Size:       info.Size(),
			CreateTime: info.ModTime(),
		})
	}

	// 按创建时间降序排序
	sort.Slice(backups, func(i, j int) bool {
		return backups[i].CreateTime.After(backups[j].CreateTime)
	})

	common.Success(ctx, backups)
}

// DeleteBackup godoc
// @Summary 删除备份文件
// @Description 删除指定的数据库备份文件
// @Tags 数据库备份
// @Accept json
// @Produce json
// @Security Bearer
// @Param filename query string true "备份文件名"
// @Success 200 {object} common.Response "成功"
// @Failure 400 {object} common.Response "请求错误"
// @Failure 500 {object} common.Response "内部错误"
// @Router /backup [delete]
func (c *BackupController) DeleteBackup(ctx *gin.Context) {
	filename := ctx.Query("filename")
	if filename == "" {
		logger.Warn("未指定备份文件")
		common.Error(ctx, fmt.Errorf("未指定备份文件"))
		return
	}

	backupPath := filepath.Join(c.backupDir, filename)
	if _, err := os.Stat(backupPath); os.IsNotExist(err) {
		logger.Warn("备份文件不存在", zap.String("path", backupPath))
		common.Error(ctx, fmt.Errorf("备份文件不存在"))
		return
	}

	if err := os.Remove(backupPath); err != nil {
		logger.Error("删除备份文件失败", zap.Error(err), zap.String("path", backupPath))
		common.Error(ctx, fmt.Errorf("删除备份失败: %v", err))
		return
	}

	logger.Info("删除备份文件成功", zap.String("filename", filename))
	common.Success(ctx, nil)
}
